Add --secret flag to image build command#41106
Conversation
Replace the hand-maintained DeleteAllBuiltImages() static list (run in both TEST_METHOD_SETUP and TEST_METHOD_CLEANUP, sweeping every built image twice per test and flooding the log with VERIFY lines) with: - A per-test DeleteImageOnExit() RAII guard so each test owns and cleans up exactly the image(s) it builds. It is best-effort and non-throwing (no VERIFY) since it may run during stack unwinding after a failure. - A single class-level DeleteImagesWithRepositoryPrefix() prune in ClassSetup and ClassCleanup as the authoritative safety net for images left behind by a crashed run. This removes the per-method sweeps, the static image list, and the excessive per-field VERIFY logging that dominated test output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implements --secret for wslc image build, matching the Docker/BuildKit CLI so Dockerfiles can consume build secrets via RUN --mount=type=secret. Supported forms (Docker parity): - id=NAME,src=PATH / id=NAME,source=PATH - secret from a file - id=NAME,env=VAR - secret from an environment variable - id=NAME,type=env|file - explicit source type - id=NAME - bare form; falls back to env var NAME When both env= and src= are given, the environment variable wins (Docker parity). Delivery: secret contents are read client-side as raw bytes and passed to the service over COM as a counted byte array, then streamed into a per-build, root-only tmpfs file (0700 dir / 0600 file) under /run/wslc-secrets/<guid> in the utility VM and exposed to buildkit via --secret id=<id>,src=<path>. The per-build directory is removed on completion. This is binary-safe (embedded NULs / arbitrary bytes) and mounts no host paths into the guest. Known gaps vs Docker: - The secret value is buffered whole in memory on the client->service hop rather than streamed; fine for typical (small) secrets, but not suited to very large payloads. - A bare id=NAME whose environment variable is unset yields an empty secret rather than erroring (minor divergence). - The accepted id character set is deliberately stricter than Docker's, as an injection guard for the generated buildkit argument. - --ssh forwarding is not implemented (separate feature). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Docker parity: --secret id=NAME with no env=/src= now fails when the id-named environment variable is undefined, instead of forwarding an empty secret. Adds an e2e test for the failure path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This pull request adds Docker-style --secret support to wslc image build, including CLI argument wiring, client-side parsing/validation and transport of raw secret bytes to the service, and server-side staging of secrets into VM tmpfs files for docker build --secret id=...,src=... consumption. It also expands E2E coverage for secret semantics and adjusts image-build test cleanup to be more robust.
Changes:
- Added
--secretCLI argument, localized help/error strings, and parsing/validation forid=...[,type=env|file][,env=...][,src=...]specs. - Plumbed secrets through the internal API (new structs + IDL) and implemented VM-side staging/cleanup for secret bytes during image builds.
- Added extensive E2E tests for secret behavior and updated test cleanup to avoid leaving built images behind.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp | Adds E2E coverage for --secret and refactors cleanup to per-test RAII + prefix sweep safety net |
| test/windows/wslc/e2e/WSLCE2EHelpers.h | Declares new helper to delete images by repository prefix |
| test/windows/wslc/e2e/WSLCE2EHelpers.cpp | Implements DeleteImagesWithRepositoryPrefix using image list --format json |
| src/windows/wslcsession/WSLCSession.cpp | Adds secrets array validation and stages secrets into VM tmpfs files for docker build |
| src/windows/wslc/tasks/ImageTasks.cpp | Implements --secret parsing/validation and forwards secrets to the service layer |
| src/windows/wslc/services/ImageService.h | Introduces BuildSecret and extends Build API to accept secrets |
| src/windows/wslc/services/ImageService.cpp | Marshals secrets into WSLCBuildSecretArray for the COM call |
| src/windows/wslc/commands/ImageBuildCommand.cpp | Registers --secret as a build argument |
| src/windows/wslc/arguments/ArgumentDefinitions.h | Adds new argument type Secret |
| src/windows/service/inc/wslc.idl | Adds WSLCBuildSecret / WSLCBuildSecretArray and extends WSLCBuildImageOptions |
| localization/strings/en-US/Resources.resw | Adds localized strings for invalid secret spec and --secret help text |
Reject an empty --secret id up-front (would produce an invalid id=,src=... spec), and record the VM mount path before calling MountWindowsFolder so an allocation failure can never leak an untracked mount. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Docker parity: a secret 'id' may not start with '-' as it would be interpreted as a command-line option. Validate this up-front in ParseSecretSpec with an actionable error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Relocate all --secret spec validation (key=value syntax, unknown keys, id required/format, unsupported type, type=file requires src, bare-id env var must be set, src file must exist) from ParseSecretSpec in ImageTasks into validation::ValidateSecretSpec so invalid specs are rejected during argument validation. ParseSecretSpec now only parses the validated spec and resolves the secret bytes. Update the UnknownType e2e test to match the argument-validation error presentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…soft/WSL into user/johnstep/build-secret
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
src/windows/wslc/services/ImageService.cpp:190
- WSLCBuildSecret.ValueSize is a ULONG, but this code blindly casts secret.Value.size() (size_t) to ULONG. For secrets larger than 4GiB this truncates the size sent to the service, potentially causing incorrect/partial writes or undefined behavior during marshaling. Add an explicit size check and fail fast before populating WSLCBuildSecret.
secretEntries.push_back(WSLCBuildSecret{
.Id = secretIdStrings.back().c_str(),
.Value = secret.Value.empty() ? nullptr : secret.Value.data(),
.ValueSize = static_cast<ULONG>(secret.Value.size()),
});
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:364
- This secret test creates a unique build context directory, which contradicts the SharedSecretBuildContext rationale above (virtiofs share slots are not released for the session lifetime). Reuse SharedSecretBuildContext here too to avoid exhausting share slots across the secret test suite.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:498
- This secret test creates a unique build context directory, which contradicts the SharedSecretBuildContext rationale above (virtiofs share slots are not released for the session lifetime). Reuse SharedSecretBuildContext here too to avoid exhausting share slots across the secret test suite.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:695
- This secret test creates a unique build context directory, which contradicts the SharedSecretBuildContext rationale above (virtiofs share slots are not released for the session lifetime). Reuse SharedSecretBuildContext here too to avoid exhausting share slots across the secret test suite.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:363
- These secret E2E tests are intended to reuse SharedSecretBuildContext() to avoid exhausting per-session virtiofs share slots (per the comment above), but this test creates a per-test context directory instead. That can still consume an additional share slot and make the suite flaky as more secret tests are added.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:497
- This secret E2E test still creates and mounts a per-test context directory instead of reusing SharedSecretBuildContext(). That undermines the intent to limit virtiofs share consumption across the secret test suite and can lead to share-slot exhaustion over the session lifetime.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:694
- This secret E2E test mounts a unique per-test context directory rather than reusing SharedSecretBuildContext(), which can consume an additional virtiofs share slot for the session lifetime and make the overall secret test suite less reliable.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
src/windows/wslcsession/WSLCSession.cpp:1028
- WSLCSession::BuildImage validates secret.Id only for leading '-' and the presence of ','/'=' before interpolating it into docker's
--secretspec. Because this is an API boundary (COM), callers other than the CLI can pass ids containing whitespace or other punctuation that Docker may reject or interpret unexpectedly. Consider validating the id character set to match the CLI validation (letters/digits plus '_', '-', '.') for defense-in-depth and consistent behavior.
// Id is interpolated into docker's comma/'='-delimited --secret spec below, so reject any ','
// or '=' a malicious caller could use to inject extra options.
RETURN_HR_IF(E_INVALIDARG, std::string_view(secret.Id).find_first_of(",=") != std::string_view::npos);
Replace ValidateSecretSpec with a single ParseSecretSpec that both validates a --secret spec and resolves its bytes. Argument validation calls it and discards the result; the build calls it again and keeps the returned BuildSecret. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (5)
src/windows/wslc/arguments/ArgumentValidation.cpp:233
- ParseSecretSpec accepts empty values for keys like 'type=', 'env=', or 'src=' (e.g.
id=x,type=), which then get treated as if the key was omitted and can silently fall back to env-var resolution. That makes malformed--secretspecs behave unexpectedly and diverges from typical Docker error handling for invalid secret specs.
auto key = part.substr(0, eq);
auto value = part.substr(eq + 1);
src/windows/wslcsession/WSLCSession.cpp:1029
- WSLCSession::BuildImage validates secret.Id only for emptiness, leading '-', and the presence of ','/'='. Since the id is interpolated into docker's
--secret id=...,src=...spec, allowing other characters (e.g. whitespace/control chars) can still produce invalid docker invocations and inconsistent behavior between CLI callers and direct COM callers. Consider enforcing the same allowed character set as the CLI parser (letters/digits/_/-/.).
RETURN_HR_IF(E_INVALIDARG, secret.Id[0] == '\0');
RETURN_HR_IF(E_INVALIDARG, secret.Id[0] == '-');
// Id is interpolated into docker's comma/'='-delimited --secret spec below, so reject any ','
// or '=' a malicious caller could use to inject extra options.
RETURN_HR_IF(E_INVALIDARG, std::string_view(secret.Id).find_first_of(",=") != std::string_view::npos);
RETURN_HR_IF(E_INVALIDARG, secret.ValueSize != 0 && secret.Value == nullptr);
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:364
- This secret test creates a unique context directory instead of using SharedSecretBuildContext(). Since virtiofs shares are not released for the session lifetime, distinct context paths can exhaust the share slot budget across the secret test suite.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:498
- This secret test creates a unique context directory instead of using SharedSecretBuildContext(). Since virtiofs shares are not released for the session lifetime, distinct context paths can exhaust the share slot budget across the secret test suite.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:695
- This secret test creates a unique context directory instead of using SharedSecretBuildContext(). Since virtiofs shares are not released for the session lifetime, distinct context paths can exhaust the share slot budget across the secret test suite.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
Add WSLCCLISecretParserUnitTests covering validation::ParseSecretSpec (env- and file-backed secrets plus invalid specs). Move the ReadEnv helper out of EnvironmentOptions into wsl::windows::common::wslutil::ReadEnvironmentVariable and reuse it for the secret env-value read in ParseSecretSpec, replacing the hand-rolled two-call GetEnvironmentVariableW logic. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the command-line spec parsers (secret, ulimit, label, driver option, filter) and the scalar value parsers (signal, timestamp, format, inspect type, memory size, duration, nano-CPUs) out of ArgumentValidation into a dedicated SpecParsing translation unit. The multi-field parsers now share a common SplitKeyValue helper. The Validate* wrappers remain in ArgumentValidation and forward to the moved parsers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (4)
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:363
- This test creates a unique context directory, but the file header comment says all secret tests must reuse a single shared context to avoid exhausting virtiofs share slots for the session lifetime. Reuse SharedSecretBuildContext() here as well so repeated secret tests don’t permanently consume additional share slots.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:497
- This secret test creates a per-test build context directory, but the shared-context helper above exists specifically to prevent exhausting the session’s limited virtiofs share slots. Using SharedSecretBuildContext() here avoids permanently consuming another share slot.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:694
- This secret test uses a unique context directory even though the class comment states all secret builds should reuse SharedSecretBuildContext() to avoid exhausting virtiofs share slots. Switching to the shared context keeps the session from permanently consuming additional mounts.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
src/windows/wslc/arguments/ArgumentValidation.cpp:116
- Argument validation currently calls ParseSecretSpec(), which materializes the secret bytes (including reading src= files). BuildImage() later calls ParseSecretSpec() again to actually send the bytes to the service, so file/env secrets get read twice and validation can fail if the file changes/disappears after validation. Consider splitting this into a lightweight ValidateSecretSpec() (syntax/keys/type/id checks only) and doing the actual byte materialization only once in the build path.
case ArgType::Since:
validation::ValidateTimestamp(execArgs.GetAll<ArgType::Since>(), m_name);
break;
case ArgType::Until:
validation::ValidateTimestamp(execArgs.GetAll<ArgType::Until>(), m_name);
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
src/windows/wslc/arguments/ArgumentValidation.cpp:109
- ArgType::Secret validation currently calls ParseSecretSpec(), which resolves the secret (reads files / env vars). The build path (ImageTasks::BuildImage) parses secrets again to actually forward them, so file/env secrets get read twice and can hit TOCTOU issues (file modified/deleted between validation and execution) and unnecessary I/O.
case ArgType::Secret:
{
for (const auto& spec : execArgs.GetAll<ArgType::Secret>())
{
std::ignore = validation::ParseSecretSpec(spec);
}
break;
}
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:364
- These failing secret tests create a unique contextDir, which will be mounted into the VM and consume an additional virtiofs share slot for the whole session (WSLCVirtualMachine::UnmountWindowsFolder keeps shares mounted in virtiofs mode). To avoid exhausting share slots, reuse SharedSecretBuildContext() here as well, since the Dockerfile is already streamed via -f.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:498
- This test creates a per-test contextDir that will be mounted and consume a virtiofs share slot for the session lifetime (UnmountWindowsFolder keeps shares mounted under virtiofs). Since the Dockerfile is streamed via -f, reuse SharedSecretBuildContext() to avoid share-slot exhaustion as more tests are added.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:695
- Like the other secret tests, this failure-case test mounts a unique contextDir into the VM, consuming another virtiofs share slot for the whole session (virtiofs shares are intentionally kept mounted in UnmountWindowsFolder). Reuse SharedSecretBuildContext() to keep share usage bounded.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
dkbennett
left a comment
There was a problem hiding this comment.
Minor nit, looks good, love all the test coverage!
Replace ad-hoc SetEnvironmentVariableW plus scope_exit cleanup (and a duplicate local ScopedEnvVar helper) with the shared ScopedEnvVariable RAII type from test/windows/Common.h, which also captures and restores any prior value on scope exit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (4)
src/windows/wslc/arguments/ArgumentValidation.cpp:106
- ArgType::Secret validation currently calls
ParseSecretSpec(), which resolves the secret value (reads env var / reads the source file into memory). The build path later parses the same specs again to actually pass secrets to the service, so this can read secret sources twice and unnecessarily materialize secret bytes during argument validation.
case ArgType::Secret:
{
for (const auto& spec : execArgs.GetAll<ArgType::Secret>())
{
std::ignore = validation::ParseSecretSpec(spec);
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:362
- These secret tests create a per-test context directory, which contradicts the
SharedSecretBuildContext()comment and can still consume additional virtiofs share slots for the session lifetime. Use the shared context directory here as well to avoid share exhaustion/flaky runs.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:496
- This test creates a unique build context directory even though the file documents that secret tests must reuse a single shared context to avoid exhausting virtiofs share slots for the session lifetime. Reuse
SharedSecretBuildContext()here too.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:689
- This secret test uses a per-test context directory, which can consume additional virtiofs share slots and contradicts the intent of
SharedSecretBuildContext(). Switch to the shared context directory to keep secret tests from exhausting the share budget.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (5)
src/windows/wslc/arguments/ArgumentValidation.cpp:109
- Argument::Validate currently calls ParseSecretSpec for ArgType::Secret, but BuildImage later calls ParseSecretSpec again to actually collect secrets. Because ParseSecretSpec resolves secret values (reads env vars and possibly reads secret files), this duplicates I/O and can make behavior depend on whether the env/file changed between validation and execution. Consider making validation syntax-only, or (simplest) don’t resolve secrets in Argument::Validate and let BuildImage be the single place that parses/resolves them.
case ArgType::Secret:
{
for (const auto& spec : execArgs.GetAll<ArgType::Secret>())
{
std::ignore = validation::ParseSecretSpec(spec);
}
break;
}
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:362
- This secret test creates a per-test context directory (unique host path). The file-level comment above explains that distinct context directories permanently consume virtiofs share slots for the session lifetime, so this can still contribute to exhausting the share budget. Reuse SharedSecretBuildContext() here as well (the Dockerfile is already passed via -f).
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:495
- This secret test creates a per-test context directory (unique host path). Since secret tests are intended to share a single context directory to avoid exhausting virtiofs share slots, this should also use SharedSecretBuildContext().
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp:689
- This secret test creates a per-test context directory (unique host path). To match the SharedSecretBuildContext() rationale and avoid consuming additional virtiofs share slots, reuse the shared context here too.
auto contextDir = testRoot / L"context";
std::error_code ec;
std::filesystem::create_directories(contextDir, ec);
THROW_HR_IF(E_FAIL, ec.value() != 0 || !std::filesystem::exists(contextDir));
src/windows/wslcsession/WSLCSession.cpp:1052
- --secret support adds secret identifiers and internal src paths to buildArgs. BuildImageStart currently logs Join(buildArgs), so these identifiers/paths will be emitted to ETL/telemetry. Even though the secret bytes aren’t logged, IDs can still be sensitive; consider redacting the --secret payloads from the logged command string.
buildArgs.push_back("--secret");
buildArgs.push_back(std::format("id={},src={}", secret.Id, secretPath));
| buildArgs.push_back(Options->Labels.Values[i]); | ||
| } | ||
|
|
||
| // Materialize each secret into a root-only tmpfs file inside the VM and hand docker a file |
There was a problem hiding this comment.
Depending on the secrets themselves, they could pretty big and potentially exhaust the memory on the /run mount.
One thing we could do instead would be to create a temporary folder, and then mount each file via virtiofs inside the guest. This will be a bit more work, but we'll be safe from any memory exhaustion
There was a problem hiding this comment.
We could even mount all of this in a new tmpfs, and unmount it once done, that way nothing can leak behind
This pull request adds support for Docker-style
--secretarguments to the image build command, enabling secure injection of secrets (from environment variables or files) into the build process. It introduces robust parsing and validation for secret specifications, updates the internal data structures and APIs to handle secrets, and ensures safe handling and cleanup of resources during the build. The most important changes are grouped below.Feature: Add Docker-style
--secretsupport to image buildsSecret) to the CLI and command definitions, along with user-facing descriptions and error messages for invalid secret specs. (src/windows/wslc/arguments/ArgumentDefinitions.h[1]localization/strings/en-US/Resources.resw[2] [3]--secretspecs, supporting secrets from environment variables or files, and matching Docker's semantics and error handling. (src/windows/wslc/tasks/ImageTasks.cpp[1] [2]Internal API and Data Structure Updates
BuildSecretandWSLCBuildSecretstructs, and updated the image build options and service interfaces to pass secrets through all layers. (src/windows/service/inc/wslc.idl[1] [2]src/windows/wslc/services/ImageService.h[3] [4]src/windows/wslc/services/ImageService.cpp[5] [6] [7]src/windows/wslc/commands/ImageBuildCommand.cpp[1]src/windows/wslc/tasks/ImageTasks.cpp[2]Resource Management and Robustness
src/windows/wslcsession/WSLCSession.cppsrc/windows/wslcsession/WSLCSession.cppL910-R934)src/windows/wslcsession/WSLCSession.cppsrc/windows/wslcsession/WSLCSession.cppR883)Summary of the Pull Request
PR Checklist
Detailed Description of the Pull Request / Additional comments
Validation Steps Performed